package de.op.projectc.objects;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;
import de.op.projectc.helper.BodyEditorLoader;
import de.op.projectc.helper.CameraHelper;
import de.op.projectc.helper.WorldHelper;
import de.op.projectc.stats.Score;

public class Heli extends GameObject {

    Body heliBody;
    Vector2 heliOrigin = new Vector2();

    Vector2 force = new Vector2();
    float forceX = 0f;
    float forceY = 0f;
    float forceRotate = 0f;
    float accelX = 0f;

    final float UP_SPEED = 60;
    final float SIDE_SPEED = 20;
    final float MAX_ANGLE = 35;

    private float PIXEL_TO_WORLD = 0f;
    float ConvertToWorld(float x){
        return x * PIXEL_TO_WORLD;
    }

	public Heli(Texture texture, float width, float height) {
		super(texture, 0, 0, width, height);

        this.PIXEL_TO_WORLD = this.getHeight() / 2;
        createBody();
        createContactListener();
	}

    private void createBody() {
        // 0. Create a loader for the file saved from the editor.
        BodyEditorLoader loader = new BodyEditorLoader(Gdx.files.internal("bodies.json"));

        BodyDef heliBodyDef = new BodyDef();
        heliBodyDef.type = BodyDef.BodyType.DynamicBody;
        heliBodyDef.fixedRotation = true;
        heliBodyDef.position.set(new Vector2(CameraHelper.getInstance().viewportWidth / 2 + this.getWidth()/2,
                this.getHeight()));

        this.heliBody = WorldHelper.getInstance().createBody(heliBodyDef);

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.density = 1f;
        fixtureDef.friction = 1f;
        fixtureDef.restitution = 0f;
        fixtureDef.filter.groupIndex = 1;

        loader.attachFixture(this.heliBody, "heli", fixtureDef, this.getWidth());

        this.heliOrigin = loader.getOrigin("heli", this.getWidth()).cpy();


        /*
        PolygonShape heliBox = new PolygonShape();
        heliBox.setAsBox(1, 1);

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = heliBox;
        fixtureDef.density = 1f;
        fixtureDef.friction = 0.75f;
        fixtureDef.restitution = 0.1f;

        heliBody.createFixture(fixtureDef);
        */

        //this.heliBody.setUserData(this);
    }

    private void createContactListener() {
        WorldHelper.getInstance().setContactListener(new ContactListener() {

            @Override
            public void beginContact(Contact contact) {
                Fixture fixtureA = contact.getFixtureA();
                Fixture fixtureB = contact.getFixtureB();

                if (fixtureA.getFilterData().groupIndex * fixtureB.getFilterData().groupIndex > 0) {
                    crash();
                    //Gdx.app.log("beginContact", "between " + fixtureA.toString() + " and " + fixtureB.toString());
                }
            }

            @Override
            public void endContact(Contact contact) {
                Fixture fixtureA = contact.getFixtureA();
                Fixture fixtureB = contact.getFixtureB();

                if (fixtureA.getFilterData().groupIndex * fixtureB.getFilterData().groupIndex > 0) {
                    //Gdx.app.log("endContact", "between " + fixtureA.toString() + " and " + fixtureB.toString());
                }
            }

            @Override
            public void preSolve(Contact contact, Manifold oldManifold) {}

            @Override
            public void postSolve(Contact contact, ContactImpulse impulse) {}
        });
    }

    private void handleInput(float delta) {
        this.force = new Vector2();
        this.forceX = 0;
        this.forceY = 0;

        //else if(this.forceRotate > 0)
         //   this.forceRotate -= delta * MAX_ANGLE;

        if(Gdx.input.isKeyPressed(Input.Keys.W)) {
            this.force.y = UP_SPEED;
            this.forceY = UP_SPEED;
        }

        if(Gdx.input.isKeyPressed(Input.Keys.A)) {
            this.force.x = -SIDE_SPEED;
            this.forceX = -SIDE_SPEED;
            this.forceRotate += delta * MAX_ANGLE;
        }
        else if(Gdx.input.isKeyPressed(Input.Keys.D)) {
            this.force.x = SIDE_SPEED;
            this.forceX = SIDE_SPEED;
            this.forceRotate -= delta * MAX_ANGLE;
        }
        else {
            if(this.forceRotate < -1 || this.forceRotate > 1)
                this.forceRotate += delta * (0 - this.forceRotate);
            else
                this.forceRotate = 0f;
        }

        this.forceRotate = Math.min(MAX_ANGLE, this.forceRotate);
        this.forceRotate = Math.max(-MAX_ANGLE, this.forceRotate);

        this.accelX = Gdx.input.getAccelerometerX();

        if(Gdx.input.isKeyPressed(Input.Keys.MINUS)) {
            CameraHelper.getInstance().zoom -= 0.2f;
        }

        if(Gdx.input.isKeyPressed(Input.Keys.PLUS)) {
            CameraHelper.getInstance().zoom += 0.2f;
        }
    }

    //TODO Spiel Ende Screen/Meldung
    public void crash() {
        Gdx.app.log("Crash: ", "Heli crashed.");
    }

	@Override
	public void update(float delta) {
        handleInput(delta);
	    
	    this.velocity.x = -this.accelX * (CameraHelper.getInstance().viewportWidth / 3);

        //Gdx.app.log("Position:", " " + this.getPositionY());

        if(Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer))
            this.heliBody.setTransform(this.heliBody.getPosition().add(this.velocity), this.accelX * 7f);

        //if(this.force.x != 0 || this.force.y != 0)
        //    this.heliBody.applyForceToCenter(this.force, true);

        if(this.forceX != 0 || this.forceY != 0)
            this.heliBody.applyForceToCenter(this.forceX, this.forceY, true);

       // if(this.forceX == 0)
         //   this.heliBody.setLinearVelocity(0, this.heliBody.getLinearVelocity().y);

        //if(this.forceX != 0)
            //this.heliBody.applyForce(new Vector2(this.forceX, 0), this.heliBody.getWorldPoint(new Vector2(this.getWidth() / 2, this.getHeight() /2)), true);

        if(this.forceRotate != 0f)
            this.heliBody.setTransform(this.heliBody.getPosition(), (float) Math.toRadians(this.forceRotate));

       /* if(this.forceRotate != 0)
            this.heliBody.applyTorque(this.forceRotate, true);
        if(this.forceRotateTablet != 0)
            this.heliBody.applyTorque(this.forceRotateTablet, true);
        */
        Vector2 heliPos = this.heliBody.getPosition().sub(this.heliOrigin);

        this.sprite.setPosition(heliPos.x, heliPos.y);
        this.sprite.setOrigin(this.heliOrigin.x, this.heliOrigin.y);
        this.sprite.setRotation(this.heliBody.getAngle() * MathUtils.radiansToDegrees);

        Score.getInstance().updateScore(ConvertToWorld(this.getPositionY()));
    }

	@Override
	public void render(SpriteBatch spriteBatch) {
		//spriteBatch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
		this.sprite.draw(spriteBatch);
	}
}
